import '../cache.dart';

/// A store will keep track of [Cache] values.
/// 
/// A [Cache] value can be inserted into the store with the
/// [set] method.
/// 
/// A [Cache] value can be extracted from the store with the 
/// [get] method by giving its unique [key]. The [get] method 
/// is also convenient for automatically updating the value
/// if needed (aka. expired or forced).
/// 
/// If multiple values have to be inserted or extracted at the
/// same time, use the [setAll] and [getAll] variants that are
/// more optimized.
abstract class CacheStore<T> {

  /// Inserts the cache [value] into the store.
  /// 
  /// If a cache value with the same key exists, it is
  /// remplaced by this new [value].
  Future<void> set(Cache<T> value);

  /// Inserts the cache [values] into the store.
  /// 
  /// If a cache values with the same keys exist, they are
  /// remplaced by this new [values].
  Future<void> setAll(List<Cache<T>> values);

  /// Get the cached data associated to the given [key].
  /// 
  /// Returns [null] if no value has been stored prior to the
  /// call.
  /// 
  /// If the [ifExpired] updater is precised, and the
  /// current cached value is expired (or the [forceUpdate]
  /// is [true]), the previous cache is replaced by the 
  /// new one.
  /// 
  /// If [forceCached] is true, the cache value will never
  /// be updated with [ifExpired].
  /// 
  /// If [sharedUpdates] if true, if an update is currently occurring
  /// for the given [key], it will be used instead of [ifExpired].
  Future<Cache<T>> get(String key, { 
    bool forceCached = false,
    bool forceUpdate = false,
    bool throwOnUpdateError = true,
    bool sharedUpdates = true,
    CacheUpdater<T> ifExpired});
  
  /// Get all the cached data associated to the given [keys].
  /// 
  /// Returns [null] if no value has been stored prior to the
  /// call for each key.
  /// 
  /// If the [ifExpired] updater is precised, and the
  /// current cached value is expired (or the [forceUpdate]
  /// is [true]), the previous cache is replaced by the 
  /// new one.
  /// 
  /// If [forceCached] is true, the cache value will never
  /// be updated with [ifExpired].
  /// 
  /// If [sharedUpdates] if true, if an update is currently occurring
  /// for the given [key], it will be used instead of [ifExpired].
  Future<List<Cache<T>>> getAll(List<String> keys, { 
    bool forceCached = false,
    bool forceUpdate = false,
    bool throwOnUpdateError = true,
    bool sharedUpdates = true,
    CacheUpdater<T> ifExpired});

  /// Removes all data associated to the given [key].
  Future<void> delete(String key);

  /// Removes all entries from cache which priority
  /// is lower than the given [priority].
  Future<void> clean(CachePriority priority);

  /// Invalidates the entry with the given [key].
  Future<void> invalidate(String key);

  /// Invalidates the entries with the given [keys].
  Future<void> invalidateAll(List<String> keys);
}